<?php

namespace app\controller;

use app\BaseController;
use think\facade\Db;

class Index extends BaseController
{
    // 首页
    public function index()
    {
        $data = $this->view_data();
        return view('/index/index', $data);
    }

    // 分类页
    public function cate($id)
    {
        $data = $this->view_data($id);
        return view('/index/index', $data);
    }

    // 详情页
    public function detail($id)
    {
        $data = $this->view_data($id);
        return view('/index/detail', $data);
    }

    /**
     * 商城中心
     */
    public function shop()
    {
        $data = $this->view_data();
        return view('/index/shop', $data);
    }

    // 商品列表
    public function shop_list()
    {
        $data = $this->view_data();
        $data['shops'] = Db::table('product')->order('id', 'desc')->select();
        return view('/index/shop_list', $data);
    }

    // 选择规格
    public function skus($pro_id)
    {
        $data = $this->view_data();
        $skus = Db::table('product_sku')->where('status', 0)->where('pro_id', $pro_id)->select();
        $product = Db::table('product')->where('id', $pro_id)->find();
        if ($skus->isEmpty() || !$product) {
            exit('<p style="text-align:center">该商品还没有添加规格</p>');
        }
        $data['skus'] = $skus->map(function ($item) use ($product) {
            $item['product'] = $product;
            return $item;
        });
        return view('/index/skus', $data);
    }


    // 私有方法：视图数据
    private function view_data($id = 0)
    {
        // 获取方法
        $action = $this->request->action();
        $map = [];
        $pageSize = 10;

        // 获取基本设置
        $setting = DB::table('setting')->where('names', 'base_setting')->find();
        $option = [];
        if ($setting && isset($setting['values'])) {
            $option = json_decode($setting['values'], true);
        }
        $siteUrl = empty($option['siteUrl']) ? '' : rtrim($option['siteUrl'], '/');

        // Seo标签
        $page = max((int)input('get.page'), 1);
        $title_arr[] = $option['title'] ?: $option['title'];
        $title_arr[] = $page > 1 ? '第' . $page . '页' : '';
        $description = $option['description'] ?: $option['description'];

        // 初始条件
        $archive_title = '最新文章';
        $url = $siteUrl . '/';
        $search = trim(input('get.search', ''));
        $crumbs[] = ['name' => '首页', 'link' => $url];
        $cate_id = $action == 'cate' ? $id : 0;
        $post_id = $action == 'detail' ? $id : 0;

        // 分类数组，按键重组
        $cates = Db::table('cates')->where('status', 0)->order('sort', 'desc')->order('id', 'asc')->select()
            ->reduce(function ($res, $next) use ($siteUrl) {
                $next['link'] = $siteUrl . '/cate/' . $next['id'] . '.html';
                $res[$next['id']] = $next;
                return $res;
            }, []);

        // 导航菜单，按键指针
        $navs = $this->navs($cates);

        // 搜索时
        if (strlen($search)) {
            $map[] = ['title', 'like', "%{$search}%"];
            $url = $siteUrl . '/?s=' . $search;
            $archive_title = '搜索' . $search;
            $crumbs[] = ['name' => '搜索结果', 'link' => 'javascript:;'];
            $title_arr[] = $archive_title;
            $description = '搜索' . $search . '的结果';
        }

        // 分类页
        $grids = explode(',', $option['grid'] ?? 0);
        if ($action === 'cate' && $cate_id) {
            $cate_ids = array_column($this->childs($cates, $cate_id), 'id'); //递归子孙
            array_unshift($cate_ids, $cate_id);
            $map[] = ['cat', 'in', $cate_ids];
            if (in_array($cate_id, $grids)) $pageSize = $option['gridNum'] ?? 24;
            $url = $siteUrl . '/cate/' . $cate_id . '.html';
            $archive_title = isset($cates[$cate_id]) ? $cates[$cate_id]['name'] : '';
            $crumbs = array_merge($crumbs, array_reverse($this->parents($cates, $cate_id))); //递归父级
            $title_arr[] = $archive_title ? $archive_title : '';
            $description = $archive_title ? '这是' . $archive_title . '归档页' : '';
        }

        // 内容页
        if ($action === 'detail' && $post_id) {
            $map[] = ['id', '=', $post_id];
            $url = $siteUrl . '/detail/' . $post_id . '.html';
            $article = Db::table('article')->where('id', $post_id)->find();
            $cate_id = $article['cat'] ?? $cate_id;
            $archive_title = $article && isset($cates[$article['cat']]) ? $cates[$article['cat']]['name'] : '';
            $crumbs = array_merge($crumbs, array_reverse($this->parents($cates, $cate_id))); //递归父级
            $crumbs[] = ['name' => '文章内容', 'link' => 'javascript:;'];
            $title_arr[] = $article ? $article['title'] : '';
            $description = $article ? mb_strimwidth(strip_tags($article['content']), 0, 140, '', 'utf-8') : '';
            // 阅读量自增
            $article && Db::table('article')->where('id', $post_id)->inc('views')->update();
        }

        /**
         * 商城中心
         */
        $navs = array_merge($navs, ['-1' => ['id' => '-1', 'pid' => 0, 'name' => '商城中心', 'link' => $siteUrl . '/shop/']]);
        $cates[-1] = ['id' => '-1', 'pid' => 0, 'name' => '商城中心', 'link' => $siteUrl . '/shop/'];
        if (substr($action, 0, 4) == 'shop') {
            $cate_id = '-1';
            $crumbs[] = ['name' => '商城中心', 'link' => 'javascript:;'];
            $title_arr[] = '商城中心';
            $description = '商城中心商品列表';
        }

        // Seo标题和描述
        $title_arr = array_filter($title_arr); //过滤空值
        $title = implode(' - ', array_reverse($title_arr));
        $description = preg_replace('/\s+/', ' ', str_replace(["&nbsp;", '"', "'", "\n", "\t", "\r"], ' ', $description));

        // 热门文章
        $hots = Db::table('article')->where('status', 0)->where('hot', 1)->order('id', 'desc')->limit(isset($option['hots']) ? (int)$option['hots'] + 1 : 6)->column('*', 'id');
        if ($action == 'detail' && isset($hots[$post_id])) {
            unset($hots[$post_id]); //排除当前文章
        } else {
            array_pop($hots); //弹出最后一篇
        }

        // 点击排行
        $hits = Db::table('article')->where('status', 0)->order('views', 'desc')->limit(isset($option['hits']) ? (int)$option['hits'] + 1 : 6)->column('*', 'id');
        if ($action == 'detail' && $post_id) {
            if (isset($hits[$post_id])) {
                unset($hits[$post_id]); //排除当前文章
            } else {
                array_pop($hits); //弹出最后一篇
            }
        }

        // 最近更新
        $news = Db::table('article')->where('status', 0)->order('id', 'desc')->limit(isset($option['news']) ? (int)$option['news'] + 1 : 6)->column('*', 'id');
        if ($action == 'detail' && $post_id) {
            if (isset($news[$post_id])) {
                unset($news[$post_id]); //排除当前文章
            } else {
                array_pop($news); //弹出最后一篇
            }
        }

        // 相关文章
        $relateds = [];
        if ($action == 'detail' && $cate_id && $post_id) {
            $cate_ids = array_column($this->childs($cates, $cate_id), 'id'); //递归子孙
            array_unshift($cate_ids, $cate_id);
            $relateds = Db::table('article')->where('status', 0)->whereIn('cat', $cate_ids)->whereLike('img', '%.%')->order('id', 'desc')->limit(isset($option['related']) ? (int)$option['related'] + 1 : 7)->column('*', 'id');
            if (isset($relateds[$post_id])) {
                unset($relateds[$post_id]); //排除当前文章
            } else {
                array_pop($relateds); //弹出最后一篇
            }
        }

        // 友情链接
        $links = [];
        if ($action == 'index') {
            $links = Db::table('links')->where('status', 0)->order('sort', 'desc')->order('id', 'asc')->limit(8)->select()->toArray();
        }

        // 条件获取文章（文章页获取一篇）
        $posts = Db::table('article')->where($map)->where('status', 0)->where('is_del', 0)->order('id', 'desc')
            ->paginate([
                'list_rows' => (int)input('get.limit', $pageSize), //分页
                'query' => $this->request->param(),
            ])
            ->each(function ($item, $key) use ($cates, $siteUrl) {
                $item['cat_name'] = isset($cates[$item['cat']]) ? $cates[$item['cat']]['name'] : '';
                $item['cat_link'] = isset($cates[$item['cat']]) ? $siteUrl . '/cate/' . $cates[$item['cat']]['id'] . '.html' : '';
                $item['link'] = $siteUrl . '/detail/' . $item['id'] . '.html';
                $item['img'] = $siteUrl . $item['img'];
                // 内容中图片，超链接替换绝对路径
                $item['content'] = preg_replace('/(<[img|a][^>]*[src|href]=["\'])(\/storage\/.+?\.[^"\']*)(["\'][^>]*>)/sim', '$1' . $siteUrl . '$2$3', $item['content']);
                return $item;
            });
        $total = $posts->total(); //记录总数

        // 获取评论列表
        $comments = [];
        if ($action == 'detail' && $post_id) {
            $comments = Db::table('comment')->where('post_id', $post_id)->where('pid', 0)->where('status', 0)->order('id', 'desc')->paginate((int)input('get.limit', 10));
            $replys = Db::table('comment')->where('post_id', $post_id)->whereIn('pid', array_column($comments->items(), 'id'))->where('status', 0)->order('id', 'desc')->select()->toArray();
            // 遍历 -id 管理回复，+id 用户回复
            $uids = array_unique(array_column($comments->items(), 'uid'));
            $uids = array_reduce(array_unique(array_values(array_column($replys, 'uid'))), function ($prev, $next) {
                $prev[] = $next;
                return $prev;
            }, $uids);
            $uids = array_unique($uids);
            // 用户头像
            $users = Db::table('users')->whereIn('id', array_filter($uids, function ($ele) {
                return $ele > 0;
            }))->select()->toArray();
            // 管理图像
            $admins = Db::table('admin')->whereIn('id', array_map(function ($elem) {
                return 0 - $elem;
            }, array_filter($uids, function ($ele) {
                return $ele < 0;
            })))->select()->toArray();
            $avatars = array_reduce($users, function ($prev, $next) {
                $prev[$next['id']] = $next;
                return $prev;
            }, []);
            $avatars = array_reduce($admins, function ($prev, $next) {
                $prev[0 - $next['id']] = $next;
                return $prev;
            }, $avatars);
            $replys = array_map(function ($item) use ($avatars) {
                $item['avatar'] = isset($avatars[$item['uid']]['avatar']) ? $avatars[$item['uid']]['avatar'] : '';
                // $item['name'] = $avatars[$item['uid']]['name'] ?? $item['name'];
                return $item;
            }, $replys);
            $comments = $comments->each(function ($item, $key) use ($replys, $avatars) {
                $item['replys'] = array_filter($replys, function ($reply) use ($item) {
                    return $reply['pid'] == $item['id'];
                });
                $item['avatar'] = isset($avatars[$item['uid']]['avatar']) ? $avatars[$item['uid']]['avatar'] : '';
                // $item['name'] = $avatars[$item['uid']]['name'] ?? $item['name'];
                $item['add_time'] = date('Y-m-d H:i:s', $item['add_time']);
                return $item;
            });
        }

        // 变量替换
        $option['statement'] = str_replace('{url}', $url, $option['statement']);

        // 登录用户
        $user = $this->app->session->get('user');

        return compact('action', 'siteUrl', 'archive_title', 'url', 'search', 'cate_id', 'post_id', 'grids', 'cates', 'navs', 'crumbs', 'posts', 'comments', 'option', 'title', 'description', 'hots', 'hits', 'news', 'relateds', 'links', 'user');
    }

    // 私有方法：导航菜单
    private function navs($datas)
    {
        $res = [];
        foreach ($datas as $data) {
            if (isset($datas[$data['pid']])) {
                $datas[$data['pid']]['children'][] = &$datas[$data['id']];
            } else {
                $res[] = &$datas[$data['id']];
            }
        }
        return $res;
    }

    // 私有方法：递归父级
    private function parents($datas, $id = 0, &$res = [])
    {
        foreach ($datas as $data) {
            if ($data['id'] == $id) {
                $res[] = $data;
                unset($datas[$id]);
                $this->parents($datas, $data['pid'], $res);
            }
        }
        return $res;
    }

    // 私有方法: 递归子孙
    private function childs($datas, $pid = 0, &$res = [])
    {
        foreach ($datas as $data) {
            if ($data['pid'] == $pid) {
                $res[] = $data;
                unset($datas[$pid]);
                $this->childs($datas, $data['id'], $res);
            }
        }
        return $res;
    }
}
